
package xj.graph2d.app.diagram;

import java.awt.geom.Rectangle2D;
import javax.swing.SwingUtilities;

import xj.graph2d.Document;
import xj.graph2d.DrawShape;
import xj.graph2d.DrawShapeBase;
import xj.graph2d.DrawShapeConstants;
import xj.graph2d.DrawShapeFactory;
import xj.graph2d.GraphDocument;
import xj.graph2d.GraphEdgeBase;
import xj.graph2d.GraphNodeBase;
import xj.graph2d.GraphView;
import xj.graph2d.app.DrawApp;
import xj.graph2d.graph.GraphLayoutManager;
import xj.graph2d.layout.DiagramLayout;

public class DiagramBuilder { 

  public DiagramBuilder(DrawApp main, String name, Document.DocumentType type) { 
    this.main = main;

    main.newProjectItem(null, name, type);
    diagram = (GraphDocument) main.getDoc();
    view = (GraphView) main.getView();
  }

  public void setVertical(boolean v) { 
    if (diagram != null) { 
      GraphLayoutManager glayout = diagram.getGraphLayoutManager();
      if (glayout instanceof DiagramLayout) { 
	DiagramLayout layout = (DiagramLayout) glayout; 
	layout.setVertical(v);
      }
    }
  }

  public void setInverted(boolean i) { 
    if (diagram != null) { 
      GraphLayoutManager glayout = diagram.getGraphLayoutManager();
      if (glayout instanceof DiagramLayout) { 
	DiagramLayout layout = (DiagramLayout) glayout; 
	layout.setInverted(i);
      }
    }
  }

  public void setRadial(boolean r) { 
    if (diagram != null) { 
      GraphLayoutManager glayout = diagram.getGraphLayoutManager();
      if (glayout instanceof DiagramLayout) { 
	DiagramLayout layout = (DiagramLayout) glayout; 
	layout.setRadial(r);
      }
    }
  }

  public void doLayout() { 
    if (diagram != null) { 
      try { 
	diagram.doLayout();
      } catch (Exception e) { 
	e.printStackTrace();
      }

      Runnable code = new Runnable() { 
	  public void run() { 
	    // adjust canvas size 
	    Rectangle2D dim = diagram.getBounds();
	    float dw = (float) (dim.getX() + dim.getWidth()) + view.getMarginWidth();
	    float dh = (float) (dim.getY() + dim.getHeight()) + view.getMarginHeight();
	    float cw = diagram.getCanvasWidth();
	    float ch = diagram.getCanvasHeight();
	    boolean needAdjust = false; 
	    if (cw < dw) {
	      diagram.setCanvasWidth(dw);
	      needAdjust = true;
	      cw = dw;
	    }
	    if (ch < dh) {
	      diagram.setCanvasHeight(dh);
	      needAdjust = true;
	      ch = dh;
	    }
	    if (needAdjust) { 
	      main.setCanvasDimension(cw, ch);
	    }

	    view.repaint();
	  }
	};

      if (SwingUtilities.isEventDispatchThread()) { 
	code.run();
      } else { 
	SwingUtilities.invokeLater(code);
      }
    }
  }

  public static DrawShape makeShape(String tempname) {  
    if (tempname != null) { 
      DrawShapeFactory factory = DrawShapeFactory.getInstance();
      DrawShapeBase proto = factory.getPrototype(tempname);
      if (proto != null) { 
	DrawShape newShape = 
	  DrawShapeFactory.cloneDrawShape(proto, null, 
					  DrawShapeConstants.CLONE_PROTOTYPE_DRAW_ATTR);
	if (newShape instanceof GraphEdgeBase) { 
	  GraphEdgeBase edge = (GraphEdgeBase) newShape; 
	  edge.setHeadOffset(0, 0);
	  edge.setTailOffset(0, 0);
	}
	return newShape;
      }
    }
    return null;
  }

  public static void addEdge(GraphDocument diagram, 
			     GraphEdgeBase edge,
			     GraphNodeBase src,
			     GraphNodeBase des) { 
    if (diagram != null && 
	edge != null &&
	src != null && 
	des != null) { 
      diagram.addEdge(edge);
      diagram.connectSource(edge, src);
      diagram.connectDestination(edge, des);	    
      edge.setHeadOffset(0, 0);
      edge.setTailOffset(0, 0);
    }
  }

  public void addEdge(GraphEdgeBase edge,
		      GraphNodeBase src,
		      GraphNodeBase des) { 
    addEdge(diagram, edge, src, des); 
  }

  protected DrawApp main;
  protected GraphDocument diagram;
  protected GraphView view;

}
